﻿using System.Diagnostics;
using System.Linq;
using System.Runtime.Serialization;
using System.Windows;
using System.Windows.Input;
using Foundation;
using Foundation.MarkupExtensions;
using Microsoft.Win32;
using Poet.Properties;
using Poet.Views;

namespace Poet.ViewModels
{
    /// <summary>
    /// Base Main View Model.
    /// </summary>
    [DataContract]
    internal abstract class RootViewModel : ViewModel
    {
        protected static readonly OpenFileDialog OpenFileDialog = new OpenFileDialog();

        protected static readonly SaveFileDialog SaveFileDialog = new SaveFileDialog();

        /// <summary>
        /// Initializes a new instance of the <see cref="RootViewModel"/> class.
        /// </summary>
        protected RootViewModel()
        {
            Initialize();
        }

        /// <summary>
        /// Gets the search and replace view model.
        /// </summary>
        public SearchViewModel SearchViewModel
        {
            get { return Store.OfType<SearchViewModel>(); }
        }

        /// <summary>
        /// Gets the font view model.
        /// </summary>
        public FontSetViewModel FontViewModel
        {
            get { return Store.OfType<FontSetViewModel>(); }
        }

        /// <summary>
        /// Gets the palette view model.
        /// </summary>
        public PaletteSetViewModel PaletteViewModel
        {
            get { return Store.OfType<PaletteSetViewModel>(); }
        }

        /// <summary>
        /// Gets the format view model.
        /// </summary>
        public FormatSetViewModel FormatViewModel
        {
            get { return Store.OfType<FormatSetViewModel>(); }
        }

        /// <summary>
        /// Gets the recent file manager view model.
        /// </summary>
        public RecentFileManagerViewModel RecentFileManagerViewModel
        {
            get { return Store.OfType<RecentFileManagerViewModel>(); }
        }

        /// <summary>
        /// Gets the settings view model.
        /// </summary>
        public SettingsViewModel SettingsViewModel
        {
            get { return Store.OfType<SettingsViewModel>(); }
        }

        /// <summary>
        /// Gets or sets the set view mode command.
        /// </summary>
        /// <value>
        /// The set view mode command.
        /// </value>
        public ICommand SetViewModeCommand { get; set; }


        [OnDeserializing]
        private void Initialize(StreamingContext context = default (StreamingContext))
        {
            SetViewModeCommand = new RoutedCommand();
            this[ApplicationCommands.Properties].Executed += OnExecute;
            this[ApplicationCommands.Properties].CanExecute += (sender, args) => args.CanExecute = true;
            this[ApplicationCommands.Help].Executed += (sender, args) => Process.Start(Settings.Default.WebSite);
            this[ApplicationCommands.CorrectionList].CanExecute += (sender, args) =>
                {
                    if (args.Parameter != null)
                        switch (args.Parameter.ToString())
                        {
                            case "ClearUnpinned":
                                args.CanExecute = RecentFileManagerViewModel.RecentFiles.Any(i => !i.IsPinned);
                                return;
                            case "ClearPinned":
                                args.CanExecute = RecentFileManagerViewModel.RecentFiles.Any(i => i.IsPinned);
                                return;
                            case "Clear":
                                args.CanExecute = RecentFileManagerViewModel.RecentFiles.Any();
                                return;
                        }

                    var recentFile = args.Parameter as RecentFileViewModel;
                    if (recentFile == null) return;
                    args.CanExecute = true;
                };
            this[ApplicationCommands.CorrectionList].Executed += (sender, args) =>
                {
                    if (args.Parameter is string)
                    {
                        var message = Localizing.ProvideValue("ClearRecentFilesMessage");
                        bool? mode = null;
                        switch (args.Parameter.ToString())
                        {
                            case "ClearUnpinned":
                                mode = false;
                                break;
                            case "ClearPinned":
                                mode = true;
                                break;
                            case "Clear":
                                break;
                        }

                        var result = MessageBox.Show(Application.Current.MainWindow, message, "Poet",
                                                     MessageBoxButton.YesNo, MessageBoxImage.Question);
                        if (result == MessageBoxResult.Yes)
                            RecentFileManagerViewModel.Clear(mode);
                        else return;
                    }

                    var recentFile = args.Parameter as RecentFileViewModel;
                    if (recentFile == null) return;
                    RecentFileManagerViewModel.RecentFiles.Remove(recentFile);
                    args.Handled = true;
                };
            this[SetViewModeCommand].Executed += (sender, args) =>
                {
                    var parameter = args.Parameter as string;
                    if (Values.ContainsKey("Topmost")) this["Topmost"] = false;
                    if (Values.ContainsKey("WindowStyle")) this["WindowStyle"] = WindowStyle.SingleBorderWindow;

                    switch (parameter)
                    {
                        case "Rich":
                            if (Values.ContainsKey("ShowToolBarTray")) this["ShowToolBarTray"] = true;
                            if (Values.ContainsKey("ShowStatusBar")) this["ShowStatusBar"] = true;
                            if (Values.ContainsKey("ShowMenu")) this["ShowMenu"] = true;
                            if (Values.ContainsKey("ShowStandartToolBar")) this["ShowStandartToolBar"] = true;
                            if (Values.ContainsKey("ShowTextEditorToolBar")) this["ShowTextEditorToolBar"] = true;
                            if (Values.ContainsKey("ShowExtensionsToolBar")) this["ShowExtensionsToolBar"] = true;
                            break;
                        case "Standart":
                            if (Values.ContainsKey("ShowToolBarTray")) this["ShowToolBarTray"] = true;
                            if (Values.ContainsKey("ShowStatusBar")) this["ShowStatusBar"] = true;
                            if (Values.ContainsKey("ShowMenu")) this["ShowMenu"] = true;
                            if (Values.ContainsKey("ShowStandartToolBar")) this["ShowStandartToolBar"] = true;
                            if (Values.ContainsKey("ShowTextEditorToolBar")) this["ShowTextEditorToolBar"] = true;
                            if (Values.ContainsKey("ShowExtensionsToolBar")) this["ShowExtensionsToolBar"] = false;
                            break;
                        case "Light":
                            if (Values.ContainsKey("ShowToolBarTray")) this["ShowToolBarTray"] = false;
                            if (Values.ContainsKey("ShowStatusBar")) this["ShowStatusBar"] = true;
                            if (Values.ContainsKey("ShowMenu")) this["ShowMenu"] = true;
                            break;
                        case "Compact":
                            if (Values.ContainsKey("ShowToolBarTray")) this["ShowToolBarTray"] = false;
                            if (Values.ContainsKey("ShowStatusBar")) this["ShowStatusBar"] = false;
                            if (Values.ContainsKey("ShowMenu")) this["ShowMenu"] = false;
                            if (Values.ContainsKey("Topmost")) this["Topmost"] = true;
                            if (Values.ContainsKey("WindowStyle")) this["WindowStyle"] = WindowStyle.None;
                            break;
                    }
                };
        }

        private static void OnExecute(object sender, ExecutedRoutedEventArgs args)
        {
            var command = args.Command;
            var parameter = args.Parameter;

            if (command == ApplicationCommands.Properties && Equals(parameter, "SetAssociations"))
            {
                new AssociationView { DataContext = new AssociationViewModel() }.ShowDialog();
            }

            if (command == ApplicationCommands.Properties && Equals(parameter, "About"))
            {
                new AboutView { DataContext = new AboutViewModel() }.ShowDialog();
            }       
        }
    }
}
